home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / MCASM.RAR / MC_ASM.EXE / WROX_ASM / CH10 / PROGRAMS / LZW1.ASM < prev    next >
Assembly Source File  |  1994-05-30  |  15KB  |  712 lines

  1. ; Compile with TASM 3.0 and latter.
  2. ; TASM lzw1.asm /MX /ZX /O
  3. ; CALL: lzw_encode(char *buffinput,int lenginput,char *buffoutput);
  4. ; CALL: lzw_decode(char *buffinput,int lenginput,char *buffoutput);
  5.  
  6. MODEL large
  7. .386
  8.  
  9. PUBLIC        _lzw_encode
  10. PUBLIC        _lzw_decode
  11.  
  12. INIT_BITS    EQU    9
  13. MAX_BITS    EQU    13        ; The number of the BITS
  14. HASHING_SHIFT    EQU    MAX_BITS - 8
  15. ; The size of the table
  16. ; Depends on MAX_BITS    TABLE_SIZE
  17. ;        13    9029
  18. ;        14    18041
  19. ;        else    5021
  20. TABLE_SIZE    EQU    9029        
  21. CLEAR_TABLE    EQU    256        ; Code to flush the string table
  22.  
  23. TERMINATOR    EQU    257        ; LZW EOF char
  24. FIRST_CODE    EQU    258        ; First code for array_code
  25. CHECK_TIME    EQU    100 ; Check comp ratio every CHECK_TIME chars input
  26.  
  27. .DATA
  28.  
  29. inputbuffer        dd    ?
  30. outputbuffer        dd    ?
  31. inputleng        dw    ?
  32.  
  33. array_code1        dd    ?
  34. array_prefix1        dd    ?
  35. array_character1    dd    ?
  36.  
  37. decode_stack        dw    4000 dup(?)
  38. ;This array holds the decoded string
  39.  
  40. num_bits        dw    INIT_BITS    ; Starting with 9 bit codes
  41. ;unsigned long bytes_in=0,bytes_out=0 /* Used to monitor compression ratio */
  42. bytes_in        dd    0
  43. bytes_out        dd    0
  44. max_code        dw    ?    ; old MAX_CODE
  45. ;unsigned long checkpoint=CHECK_TIME  /* For compression ratio monitoring */
  46. checkpoint        dd    CHECK_TIME
  47.  
  48. output_bit_buffer    dd    0
  49. output_bit_count    dw    0
  50. input_bit_buffer    dd    0
  51. input_bit_count        dw    0
  52.  
  53. input_ptr        dw    ?    ; Positions in the buffers
  54. output_ptr        dw    ?
  55.  
  56. .CODE
  57.  
  58. MAXVAL        PROC    NEAR
  59.         PUSH    CX
  60.         MOV    CX,AX
  61.         MOV    AX,1
  62.         SHL    AX,CL
  63.         DEC    AX
  64.         POP    CX
  65.         RET
  66. MAXVAL        ENDP
  67.  
  68. _lzw_encode    PROC    C FAR
  69.         ARG    ibuf:dword,ilng:word,obuf:dword
  70.         LOCAL    next_code:word,character:word,string_code:word,\
  71.             index:word,ratio_new:word,ratio_old:word
  72.         USES    bx,cx,dx,di,si,es,ds
  73.  
  74.         mov    ax,@DATA
  75.         mov    ds,ax
  76.  
  77.         mov    bx,TABLE_SIZE    ; Allocate memory
  78.         mov    cl,3        ; bx*2/16
  79.         shr    bx,cl
  80.         inc    bx
  81.         mov    ah,48h
  82.         int    21h
  83.         jnc    @@mem_aloc_020
  84.         jmp    @@mem_aloc_err
  85. @@mem_aloc_020:    mov    word ptr array_code1+2,ax
  86.         mov    word ptr array_code1,0
  87.  
  88.         mov    bx,TABLE_SIZE
  89.         mov    cl,3
  90.         shr    bx,cl
  91.         inc    bx
  92.         mov    ah,48h
  93.         int    21h
  94.         jnc    @@mem_aloc_030
  95.         jmp    @@mem_aloc_er1
  96. @@mem_aloc_030:    mov    word ptr array_prefix1+2,ax
  97.         mov    word ptr array_prefix1,0
  98.  
  99.         mov    bx,TABLE_SIZE
  100.         mov    cl,3
  101.         shr    bx,cl
  102.         inc    bx
  103.         mov    ah,48h
  104.         int    21h
  105.         jnc    @@mem_aloc_040
  106.         jmp    @@mem_aloc_er2
  107. @@mem_aloc_040:    mov    word ptr array_character1+2,ax
  108.         mov    word ptr array_character1,0
  109.  
  110.         mov    eax,ibuf            ; Initialize segments
  111.         mov    inputbuffer,eax
  112.         mov    eax,obuf
  113.         mov    outputbuffer,eax
  114.         mov    ax,ilng
  115.         mov    inputleng,ax
  116.  
  117.         mov    bytes_in,0
  118.         mov    bytes_out,0
  119.         mov    checkpoint,CHECK_TIME
  120.         mov    output_bit_buffer,0
  121.         mov    output_bit_count,0
  122.         mov    input_bit_buffer,0
  123.         mov    input_bit_count,0
  124.         mov    num_bits,INIT_BITS
  125.  
  126.         mov    ax,word ptr array_code1+2
  127.         mov    es,ax
  128.         mov    input_ptr,0
  129.         mov    output_ptr,0
  130.  
  131.         mov    ax,num_bits
  132.         call    MAXVAL
  133.         mov    max_code,ax
  134.  
  135.         mov    ax,FIRST_CODE
  136.         mov    next_code,ax
  137.         mov    ax,100
  138.         mov    ratio_old,ax
  139. ; Initialize the string table first
  140.         mov    cx,TABLE_SIZE
  141.         mov    ax,word ptr array_code1+2
  142.         mov    es,ax
  143.         mov    di,word ptr array_code1
  144.         mov    ax,-1
  145.         cld
  146.     rep    stosw
  147. ; Get the first code
  148. ; Read byte from ax. Return - ah - eof=0 else =1, al - byte.
  149.         call    getc
  150.         xor    ah,ah
  151.         mov    string_code,ax
  152. ; Main compression loop
  153. @@main_comp_010:call    getc
  154.         cmp    ah,0
  155.         jne    @@main_comp_020
  156. ; Exit from main_comp.
  157.         jmp    @@main_comp_090
  158. @@main_comp_020:xor    ah,ah
  159.         mov    character,ax
  160.  
  161.         inc    dword ptr bytes_in
  162.  
  163.         mov    ax,string_code
  164.         mov    bx,character
  165.         call    find_match C,ax,bx
  166.         mov    index,ax
  167.  
  168.         mov    bx,ax
  169.         shl    bx,1
  170.         mov    di,bx
  171.         add    di,word ptr array_code1
  172.         mov    ax,word ptr array_code1+2
  173.         mov    es,ax
  174.         mov    ax,word ptr es:[di]        ; bx*2
  175.         cmp    ax,-1
  176.         je    @@main_comp_030
  177.             mov    string_code,ax
  178.             jmp    @@main_comp_080
  179. @@main_comp_030:mov    ax,next_code
  180.         cmp    ax,max_code
  181.         ja    @@main_comp_040
  182.             mov    word ptr es:[di],ax
  183.             inc    word ptr next_code
  184.  
  185.             mov    di,bx
  186.             add    di,word ptr array_prefix1
  187.             mov    ax,word ptr array_prefix1+2
  188.             mov    es,ax
  189.             mov    ax,string_code
  190.             mov    word ptr es:[di],ax
  191.  
  192.             mov    di,bx
  193.             add    di,word ptr array_character1
  194.             mov    ax,word ptr array_character1+2
  195.             mov    es,ax
  196.             mov    ax,character
  197.             mov    word ptr es:[di],ax
  198. @@main_comp_040:
  199. ; Send out current code
  200.             mov    ax,string_code
  201.             call    output_code C,ax
  202.  
  203.             mov    ax,character
  204.             mov    string_code,ax
  205. ; Is table Full?
  206.             mov    ax,next_code
  207.             cmp    ax,max_code
  208.             ja    @@main_comp_045
  209.             jmp    @@main_comp_080
  210. @@main_comp_045:
  211. ; Any more bits?
  212.                 mov    ax,num_bits
  213.                 cmp    ax,MAX_BITS
  214.                 jae    @@main_comp_050
  215. ; Increment code size then
  216.                     inc    ax
  217.                     mov    num_bits,ax
  218.                     call    MAXVAL
  219.                     mov    max_code,ax
  220.                     jmp    @@main_comp_080
  221. ; At checkpoint?
  222. @@main_comp_050:        mov    ax,word ptr bytes_in+2
  223.                 mov    dx,word ptr bytes_in
  224.                 cmp    ax,word ptr checkpoint+2
  225.                 jae    @@main_comp_055
  226.                 jmp    @@main_comp_080
  227. @@main_comp_055:        cmp    dx,word ptr checkpoint
  228.                 ja    @@main_comp_056
  229.                 jmp    @@main_comp_080
  230. @@main_comp_056:            mov    bx,num_bits
  231.                     cmp    bx,MAX_BITS
  232.                     jne    @@main_comp_070
  233.                         mov    ax,word ptr bytes_out
  234.                         mov    cx,100
  235.                         mul    cx
  236.                         mov    cx,word ptr bytes_in
  237.                         div    cx
  238. ; New compression ratio
  239.                         mov    word ptr ratio_new,ax
  240. ; Has ratio degraded?
  241.                         cmp    ax,ratio_old
  242.                         jbe    @@main_comp_060
  243. ; YES,flush string table
  244.                             mov    ax,CLEAR_TABLE
  245.                             call    output_code C,ax
  246.                             mov    num_bits,INIT_BITS
  247. ; Reset to FIRST_CODE
  248.                             mov    next_code,FIRST_CODE
  249. ; Re-Initialize this stuff
  250.                             mov    ax,num_bits
  251.                             call    MAXVAL
  252.                             mov    max_code,ax
  253.                             xor    ax,ax
  254.                             mov    word ptr bytes_in,ax
  255.                             mov    word ptr bytes_in+2,ax
  256.                             mov    word ptr bytes_out,ax
  257.                             mov    word ptr bytes_out+2,ax
  258. ; Reset compression ratio
  259.                             mov    ax,100
  260.                             mov    ratio_old,ax
  261. ; Reset code value array
  262.                             mov    cx,TABLE_SIZE
  263.                             mov    di,word ptr array_code1
  264.                             mov    ax,word ptr array_code1+2
  265.                             mov    es,ax
  266.                             mov    ax,-1
  267.                             cld
  268.                         rep    stosw
  269.                             jmp    short @@main_comp_070
  270. ; NO, then save new compression ratio
  271. @@main_comp_060:                mov    ratio_old,ax
  272. ; Set new checkpoint
  273. @@main_comp_070:            mov    eax,bytes_in
  274.                     add    eax,CHECK_TIME
  275.                     mov    checkpoint,eax
  276. @@main_comp_080:
  277.         jmp    @@main_comp_010
  278. ; Output the last code
  279. @@main_comp_090:mov    ax,string_code
  280.         call    output_code C,ax
  281. ; Handles special case for bit
  282.         mov    bx,next_code
  283.         cmp    bx,max_code
  284.         jne    @@main_comp_100
  285. ; increment on EOF
  286.             inc    word ptr num_bits
  287. ; Output the end of buffer code
  288. @@main_comp_100:mov    ax,TERMINATOR
  289.         call    output_code C,ax
  290. ; Flush the output buffer
  291.         xor    bx,bx
  292.         call    output_code C,bx
  293.         call    output_code C,bx
  294.         call    output_code C,bx
  295.  
  296.         mov    ax,word ptr array_character1+2
  297.         call    free_memory
  298.         mov    ax,word ptr array_prefix1+2
  299.         call    free_memory
  300.         mov    ax,word ptr array_code1+2
  301.         call    free_memory
  302.         mov    ax,output_ptr
  303.         ret
  304.  
  305. @@mem_aloc_er2:    mov    ax,word ptr array_prefix1+2
  306.         call    free_memory
  307. @@mem_aloc_er1:    mov    ax,word ptr array_code1+2
  308.         call    free_memory
  309. @@mem_aloc_err:    xor    ax,ax
  310.         ret
  311.  
  312. ; This is the hashing routine.
  313. find_match    PROC    C NEAR
  314. ; Return AX
  315.         ARG    hash_prefix:word,hash_character:word
  316.         LOCAL    index:word,foffset:word
  317.         USES    bx,cx,di,si
  318.  
  319.         mov    ax,hash_character
  320.         mov    cx,HASHING_SHIFT
  321.         shl    ax,cl
  322.         xor    ax,hash_prefix
  323.         mov    index,ax
  324.         cmp    ax,0
  325.         jne    @@find_mtch_010
  326.             mov    bx,1
  327.             mov    foffset,bx
  328.             jmp    short    @@find_mtch_020
  329. @@find_mtch_010:    mov    bx,TABLE_SIZE
  330.             sub    bx,ax
  331.             mov    foffset,bx
  332. @@find_mtch_020:mov    bx,word ptr array_code1+2
  333.         mov    es,bx
  334.         mov    bx,ax
  335.         mov    di,ax
  336.         shl    di,1
  337.         mov    si,di
  338.         add    di,word ptr array_code1
  339.         mov    ax,-1
  340.         cmp    ax,word ptr es:[di]
  341.         jne    @@find_mtch_030
  342.             mov    ax,bx
  343.             ret
  344. @@find_mtch_030:mov    di,si
  345.         add    di,word ptr array_prefix1
  346.         mov    ax,word ptr array_prefix1+2
  347.         mov    es,ax
  348.         mov    ax,word ptr es:[di]
  349.         cmp    ax,hash_prefix
  350.         jne    @@find_mtch_040
  351.         mov    di,si
  352.         add    di,word ptr array_character1
  353.         mov    ax,word ptr array_character1+2
  354.         mov    es,ax
  355.         mov    ax,word ptr es:[di]
  356.         cmp    ax,hash_character
  357.         jne    @@find_mtch_040
  358.             mov    ax,bx
  359.             ret
  360. @@find_mtch_040:sub    bx,foffset
  361.         cmp    bx,0
  362.         jge    @@find_mtch_050
  363.             add    bx,TABLE_SIZE
  364. @@find_mtch_050:mov    index,bx
  365.         mov    ax,bx
  366.         jmp    @@find_mtch_020
  367. find_match    ENDP
  368.  
  369. ; Output a variable length code.
  370. output_code    PROC    C NEAR
  371.         ARG    ocode:word
  372.         LOCAL    output_var:dword
  373.         USES    ax,bx,cx,dx
  374.  
  375.         mov    eax,output_bit_buffer
  376.         mov    bx,ocode
  377.         mov    word ptr output_var,bx
  378.         xor    bx,bx
  379.         mov    word ptr output_var+2,bx
  380.         mov    ebx,output_var
  381.         mov    cx,32
  382.         sub    cx,num_bits
  383.         sub    cx,output_bit_count
  384.         shl    ebx,cl
  385.         or    eax,ebx
  386.         mov    output_bit_buffer,eax
  387.         mov    bx,output_bit_count
  388.         add    bx,num_bits
  389.         mov    output_bit_count,bx
  390.  
  391. @@output_010:    cmp    bx,8
  392.         jb    @@output_020
  393.  
  394.         mov    eax,output_bit_buffer
  395.         mov    cl,24
  396.         shr    eax,cl
  397.  
  398.         call    putc C,ax
  399.  
  400.         mov    eax,output_bit_buffer
  401.         mov    cl,8
  402.         shl    eax,cl
  403.         mov    output_bit_buffer,eax
  404.         sub    bx,8
  405.         mov    output_bit_count,bx
  406.         inc    dword ptr bytes_out
  407.         jmp    short @@output_010
  408. @@output_020:    ret
  409. output_code    ENDP
  410.  
  411. _lzw_encode    ENDP
  412.  
  413. ; LZW decompressor
  414. _lzw_decode    PROC    C FAR
  415.         ARG    ibuf:dword,ilng:word,obuf:dword
  416.         LOCAL    next_code:word,new_code:word,old_code:word,\
  417.             character:word,counter:word,clear_flag:word,\
  418.             string:word
  419.         USES    bx,cx,dx,di,si,ds,es
  420.  
  421.         mov    ax,@data
  422.         mov    ds,ax
  423.  
  424.         mov    bx,TABLE_SIZE
  425.         mov    cl,3
  426.         shr    bx,cl
  427.         inc    bx
  428.         mov    ah,48h
  429.         int    21h
  430.         jnc    @@dem_aloc_030
  431.         jmp    @@dem_aloc_err
  432. @@dem_aloc_030:    mov    word ptr array_prefix1+2,ax
  433.         mov    word ptr array_prefix1,0
  434.  
  435.         mov    bx,TABLE_SIZE
  436.         mov    cl,3
  437.         shr    bx,cl
  438.         inc    bx
  439.         mov    ah,48h
  440.         int    21h
  441.         jnc    @@dem_aloc_040
  442.         jmp    @@dem_aloc_er2
  443. @@dem_aloc_040:    mov    word ptr array_character1+2,ax
  444.         mov    word ptr array_character1,0
  445.  
  446.         mov    bytes_in,0
  447.         mov    bytes_out,0
  448.         mov    checkpoint,CHECK_TIME
  449.         mov    output_bit_buffer,0
  450.         mov    output_bit_count,0
  451.         mov    input_bit_buffer,0
  452.         mov    input_bit_count,0
  453.         mov    num_bits,INIT_BITS
  454.  
  455.         mov    eax,ibuf            ; Initialize segments
  456.         mov    inputbuffer,eax
  457.         mov    ax,ilng
  458.         mov    inputleng,ax
  459.         mov    eax,obuf
  460.         mov    outputbuffer,eax
  461.  
  462.         mov    input_ptr,0
  463.         mov    output_ptr,0
  464.  
  465.         mov    ax,INIT_BITS
  466.         mov    num_bits,ax
  467.         call    MAXVAL
  468.         mov    max_code,ax
  469.  
  470.         mov    next_code,FIRST_CODE
  471.         mov    counter,0
  472. ; Need to clear the code value array
  473.         mov    clear_flag,1
  474.  
  475. @@expand_000:    call    input_code
  476.         mov    new_code,ax
  477.         cmp    ax,TERMINATOR
  478.         jne    @@expand_010
  479.         jmp    @@expand_100
  480. ; Initialize or Re-Initialize
  481. @@expand_010:        mov    ax,clear_flag
  482.             cmp    ax,1
  483.             jne    @@expand_020
  484.                 mov    clear_flag,0
  485.                 mov    ax,new_code
  486.                 mov    old_code,ax
  487.                 mov    character,ax
  488.  
  489.                 call    putc C,ax
  490.  
  491.                 jmp    @@expand_000
  492. ; Clear string table
  493. @@expand_020:        mov    ax,new_code
  494.             cmp    ax,CLEAR_TABLE
  495.             jne    @@expand_030
  496.                 mov    clear_flag,1
  497.                 mov    ax,INIT_BITS
  498.                 mov    num_bits,ax
  499.                 mov    next_code,FIRST_CODE
  500.                 call    MAXVAL
  501.                 mov    max_code,ax
  502.                 jmp    @@expand_000
  503. @@expand_030:        mov    ax,counter
  504.             inc    ax
  505.             cmp    ax,1000
  506.             jne    @@expand_040
  507.                 xor    ax,ax
  508. @@expand_040:        mov    counter,ax
  509. ; Check for string+char+string
  510.             mov    ax,new_code
  511.             cmp    ax,next_code
  512.             jb    @@expand_050
  513.                 mov    ax,character
  514.                 mov    decode_stack[0],ax
  515.                 mov    bx,old_code
  516.                 mov    ax,2
  517.                 call    decode_string C,ax,bx
  518.                 mov    string,ax
  519.                 jmp    short @@expand_060
  520.  
  521. @@expand_050:            xor    ax,ax
  522.                 mov    bx,new_code
  523.                 call    decode_string C,ax,bx
  524.                 mov    string,ax
  525. ; Output decoded string in reverse
  526. @@expand_060:        mov    bx,string
  527.             mov    di,bx
  528.             mov    ax,decode_stack[di]
  529.             mov    character,ax
  530.  
  531. @@expand_070:        cmp    bx,0
  532.             jl    @@expand_080
  533.                 mov    di,bx
  534.                 mov    cx,decode_stack[di]
  535.  
  536.                 call    putc C,cx
  537.  
  538.                 sub    bx,2
  539.                 jmp    short @@expand_070
  540. @@expand_080:        mov    string,bx
  541. ; Add to string table if not full
  542.             mov    bx,next_code
  543.             cmp    bx,max_code
  544.             ja    @@expand_090
  545.                 mov    di,bx
  546.                 shl    di,1
  547.                 mov    si,di
  548.                 add    di,word ptr array_prefix1
  549.                 mov    ax,word ptr array_prefix1+2
  550.                 mov    es,ax
  551.                 mov    ax,old_code
  552.                 mov    word ptr es:[di],ax
  553.                 mov    di,si
  554.                 add    di,word ptr array_character1
  555.                 mov    ax,word ptr array_character1+2
  556.                 mov    es,ax
  557.                 mov    ax,character
  558.                 mov    word ptr es:[di],ax
  559.                 inc    bx
  560.                 mov    next_code,bx
  561.  
  562.                 cmp    bx,max_code
  563.                 jne    @@expand_090
  564.                 mov    ax,num_bits
  565.                 cmp    ax,MAX_BITS
  566.                 jae    @@expand_090
  567.                     inc    ax
  568.                     mov    num_bits,ax
  569.                     call    MAXVAL
  570.                     mov    max_code,ax
  571. @@expand_090:        mov    ax,new_code
  572.             mov    old_code,ax
  573.         jmp    @@expand_000
  574.  
  575.  
  576. @@expand_100:    mov    ax,word ptr array_character1+2
  577.         call    free_memory
  578.         mov    ax,word ptr array_prefix1+2
  579.         call    free_memory
  580.         mov    ax,output_ptr
  581.         ret
  582.  
  583. @@dem_aloc_er2:    mov    ax,word ptr array_prefix1+2
  584.         call    free_memory
  585. @@dem_aloc_err:    xor    ax,ax
  586.         ret
  587.  
  588. ; Decode a string from the string table, storing it in a buffer.
  589. ; The buffer can then be output in reverse order by the expansion
  590. ; program.
  591. decode_string    PROC    C NEAR
  592.         ARG    buffer:word,ocode:word
  593.         USES    bx,cx,dx,si,di
  594.  
  595.         mov    bx,buffer
  596.         xor    cx,cx
  597. @@dec_str_000:    mov    dx,ocode
  598.         cmp    dx,255
  599.         jbe    @@dec_str_010
  600.             mov    di,dx
  601.             shl    di,1
  602.             mov    si,di
  603.             add    di,word ptr array_character1
  604.             mov    ax,word ptr array_character1+2
  605.             mov    es,ax
  606.             mov    ax,word ptr es:[di]
  607.             mov    decode_stack[bx],ax
  608.             add    bx,2
  609.  
  610.             mov    di,si
  611.             add    di,word ptr array_prefix1
  612.             mov    ax,word ptr array_prefix1+2
  613.             mov    es,ax
  614.             mov    ax,word ptr es:[di]
  615.             mov    dx,ax
  616.             mov    ocode,ax
  617.  
  618.             cmp    cx,4000
  619.             jb    @@dec_str_000
  620.                 mov    ax,4c01h
  621.                 int    21h
  622. @@dec_str_010:    mov    di,bx
  623.         mov    ax,ocode
  624.         mov    decode_stack[di],ax
  625.         mov    ax,bx
  626.         ret
  627. decode_string    ENDP
  628.  
  629. ; Input a variable length code.
  630. input_code    PROC    C NEAR
  631.         LOCAL    return_value:word,input_var:dword
  632.         USES    bx,cx
  633.  
  634.         mov    ax,input_bit_count
  635. @@input_010:    cmp    ax,24
  636.         ja    @@input_020
  637.             xor    ax,ax
  638.             mov    word ptr input_var+2,ax
  639.  
  640.             call    getc
  641.  
  642.             xor    ah,ah
  643.             mov    word ptr input_var,ax
  644.             mov    eax,input_var
  645.             mov    cx,24
  646.             sub    cx,input_bit_count
  647.             shl    eax,cl
  648.             or    input_bit_buffer,eax
  649.             mov    ax,8
  650.             add    ax,input_bit_count
  651.             mov    input_bit_count,ax
  652.             jmp    @@input_010
  653. @@input_020:    mov    cx,32
  654.         sub    cx,num_bits
  655.         mov    eax,input_bit_buffer
  656.         shr    eax,cl
  657.         mov    return_value,ax
  658.         mov    cx,num_bits
  659.         mov    eax,input_bit_buffer
  660.         shl    eax,cl
  661.         mov    input_bit_buffer,eax
  662.         mov    ax,num_bits
  663.         sub    input_bit_count,ax
  664.         mov    ax,return_value
  665.         ret
  666. input_code    ENDP
  667.  
  668. _lzw_decode    ENDP
  669.  
  670. ; Get char
  671. getc        PROC    C NEAR
  672.         USES    bx,di,es
  673. ; Return : EOF - ah=0 else ah=1, al=byte
  674.         xor    ax,ax
  675.         mov    bx,input_ptr
  676.         cmp    bx,inputleng
  677.         jae    @@getc_eof
  678.         mov    ax,word ptr inputbuffer+2
  679.         mov    es,ax
  680.         mov    di,word ptr inputbuffer
  681.         mov    al,byte ptr es:[bx+di]
  682.         inc    word ptr input_ptr
  683.         mov    ah,1
  684. @@getc_eof:    ret
  685. getc        ENDP
  686.  
  687. ; Put char
  688. putc        PROC    C NEAR
  689.         ARG    character:byte
  690.         USES    ax,bx,di,es
  691.         mov    bx,output_ptr
  692.         mov    ax,word ptr outputbuffer+2
  693.         mov    es,ax
  694.         mov    di,word ptr outputbuffer
  695.         mov    al,character
  696.         mov    byte ptr es:[bx+di],al
  697.         inc    word ptr output_ptr
  698.         ret
  699. putc        ENDP
  700.  
  701. ; Procedure for free memory.
  702. ; INPUT:    AX=segment adress (paragraph) of memory to realease.
  703. free_memory    PROC    NEAR
  704.         mov    bx,ax
  705.         mov    ah,49h
  706.         mov    es,bx
  707.         int    21h
  708.         ret
  709. free_memory    ENDP
  710.  
  711.         END
  712.